home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1997
/
HAM Radio 1997.iso
/
vcls
/
simage
/
simage.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-04-08
|
19KB
|
637 lines
{Donated to the public domain 1-May-95 by Paul Peterson, Summit Software, Inc.}
{Please report any problems to 72371,1136 via CIS Mail)
{This component makes it much easer to display 256 color BMP files in
Delphi. It will scale the image (or a rectangle of the image) up or down to
best fit into the designed size of the component. It includes a cropping
tool that a user can use at run-time to frame the part of the image of
interest. See the BMPView demo app for how this component is used. The
'ChangeFromFile() method is the main way to control this component}
unit Simage;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Forms, Controls,
extctrls, StdCtrls;
Type
TCropHandle = (NoHandle,INNER,UR,UL,BR,BL,LS,RS,TS,BS);
Const
Yes = True;
No = False;
type
TSimage = class(TImage)
procedure loaded; override;
constructor create(AOwner : Tcomponent); override;
destructor Destroy; override;
procedure MouseMove(
Shift : TShiftState;
X, Y : Integer); override;
procedure click; override;
procedure SizeAndShow;
procedure HideNow;
procedure ChangeFromFile(
const FileName : string;
Crop : Trect;
Show_Cropped : boolean;
Actual_Size : boolean);
procedure ReplaceWith(
fromImage : TSimage;
Crop : Trect;
Show_Cropped : boolean;
Actual_Size : boolean);
procedure ReDraw(
Crop : Trect;
Show_Cropped : boolean;
Actual_Size : boolean);
function get_filename : string;
function get_rect : Trect;
procedure SetDesignedSize(
t : integer;
l : integer;
w : integer;
h : integer);
procedure GetDesignedSize(
Var t : integer;
Var l : integer;
Var w : integer;
Var h : integer);
procedure draw_croptool(
Crop : Trect);
procedure croptool_off(
var changed : boolean;
var Crop : Trect);
procedure croptool_on;
public
OrigPict : TPicture;
curfilename : string;
private
procedure erasecrop;
function validcrop(
var rect : Trect;
var pict : Tpicture
) : boolean;
private
oldx,
oldy : integer;
DesignedTop,
DesignedLeft,
DesignedWidth,
DesignedHeight : integer;
CropRectActual,
CropRectScaled,
CropOutside : Trect;
CropHands : array[INNER..BS] of Trect;
CropCopy : TBitmap;
CropChanged,
valid_crop,
ShowCropped,
ShowActualSize,
CropToolOn : boolean;
CropMoveHandle : TCropHandle;
sratio : real;
end;
procedure Register;
{------------------------------------------------------------------------}
implementation
{------------------------------------------------------------------------}
procedure Register;
begin
RegisterComponents('Samples',[TSimage]);
end;
{------------------------------------------------------------------------}
constructor TSimage.create(AOwner : Tcomponent);
begin
inherited create(AOwner);
OrigPict := TPicture.create;
curfilename := '';
CropToolOn := no;
CropMoveHandle := noHandle;
valid_crop := no;
end;
{------------------------------------------------------------------------}
destructor TSimage.Destroy;
begin
OrigPict.free;
inherited Destroy;
end;
{------------------------------------------------------------------------}
procedure TSimage.click;
begin
if (CropMoveHandle = noHandle) then inherited click;
end;
{------------------------------------------------------------------------}
procedure TSimage.MouseMove(
Shift : TShiftState;
X, Y : Integer);
var
cp : TCropHandle;
found : boolean;
xd,yd : integer;
NewRect : Trect;
{------------------------------------------------------------------------}
function in_rect(var arect : Trect) : boolean;
begin
with arect do
in_rect := (x > left) and (x < right) and (y > top) and (y < bottom);
end;
{------------------------------------------------------------------------}
{------------------------------------------------------------------------}
begin
inherited MouseMove(Shift,x,y);
if not CropToolOn then exit;
if (x < -10) or (y < -10) or (x > Width + 10) or (y > Height+ 10) then
exit;
found := no;
if (CropMoveHandle <> noHandle) and (ssLeft in shift) then
begin
found := yes;
if (x <> oldx) or (y <> oldy) then
begin
NewRect := CropRectScaled;
with NewRect do
begin
xd := x - oldx;
yd := y - oldy;
case CropMoveHandle of
INNER :
begin
inc(left,xd);
inc(right,xd);
inc(top,yd);
inc(bottom,yd);
end;
UR :
begin
inc(right,xd);
inc(top,yd);
end;
UL :
begin
inc(left,xd);
inc(top,yd);
end;
BR :
begin
inc(right,xd);
inc(bottom,yd);
end;
BL :
begin
inc(left,xd);
inc(bottom,yd);
end;
LS : inc(left,xd);
RS : inc(right,xd);
TS : inc(top,yd);
BS : inc(bottom,yd);
end;
if left >= right then
if xd > 0 then
right := left + 1
else
left := right - 1;
if top >= bottom then
if yd > 0 then
bottom := top + 1
else
top := bottom - 1;
if (right >= 0) and (bottom >= 0)
and (left <= width) and (top <= height) then
begin
EraseCrop;
CropRectScaled := NewRect;
draw_croptool(CropRectScaled);
CropChanged := yes;
end;
end;
end;
end
else
begin
if in_rect(CropOutside) then
begin
for cp := INNER to high(TCropHandle) do
if in_rect(cropHands[cp]) then
begin
CropMoveHandle := cp;
found := yes;
case cp of
inner : cursor := 2;
UR,BL : cursor := crSizeNESW;
UL,BR : cursor := crSizeNWSE;
LS,RS : cursor := crSizeWE;
TS,BS : cursor := crSizeNS;
end;
break;
end;
end;
end;
if not found then
begin
cursor := crDefault;
CropMoveHandle := noHandle;
end;
oldx := x;
oldy := y;
end;
{------------------------------------------------------------------------}
procedure TSimage.loaded;
begin
inherited loaded;
DesignedTop := Top;
DesignedLeft := Left;
DesignedWidth := width;
DesignedHeight := height;
stretch := false;
autosize := false;
center := false;
end;
{------------------------------------------------------------------------}
function TSimage.validcrop(
var rect : Trect;
var pict : Tpicture
) : boolean;
begin
with rect,pict.bitmap do
begin
if left < 0 then left := width div 4;
if top < 0 then top := height div 4;
if right > width then right := (width div 4) * 3;
if bottom > height then bottom := (height div 4) * 3;
validcrop := ((left < right) and (top < bottom));
end;
end;
{------------------------------------------------------------------------}
procedure TSimage.ChangeFromFile(
const FileName : string;
Crop : Trect;
Show_Cropped : boolean;
Actual_Size : boolean);
var
dumbool : boolean;
rect : Trect;
l : longint;
SaveCursor : HCursor;
begin
SaveCursor := screen.cursor;
screen.cursor := crHourGlass;
update;
if CropToolOn then croptool_off(dumbool,rect);
curfilename := filename;
if filename = '' then
begin
HideNow;
OrigPict.assign(nil);
picture.assign(nil);
end
else
begin
OrigPict.LoadFromFile(FileName);
CropRectActual := Crop;
ShowCropped := Show_Cropped;
ShowActualSize := Actual_Size;
valid_crop := validcrop(CropRectActual,OrigPict);
HideNow;
picture.assign(Origpict);
SizeAndShow;
end;
screen.cursor := SaveCursor;
end;
{------------------------------------------------------------------------}
procedure TSimage.ReplaceWith(
fromImage : TSimage;
Crop : Trect;
Show_Cropped : boolean;
Actual_Size : boolean);
var
dumbool : boolean;
rect : Trect;
SaveCursor : HCursor;
begin
SaveCursor := screen.cursor;
screen.cursor := crHourGlass;
if CropToolOn then croptool_off(dumbool,rect);
curfilename := fromImage.get_filename;
OrigPict.assign(fromImage.OrigPict);
CropRectActual := Crop;
ShowCropped := Show_Cropped;
ShowActualSize := Actual_Size;
valid_crop := validcrop(CropRectActual,Origpict);
HideNow;
picture.assign(Origpict);
SizeAndShow;
screen.cursor := SaveCursor;
end;
{------------------------------------------------------------------------}
procedure TSimage.ReDraw(
Crop : Trect;
Show_Cropped : boolean;
Actual_Size : boolean);
var
SaveCursor : HCursor;
begin
SaveCursor := screen.cursor;
screen.cursor := crHourGlass;
if curfilename <> '' then
begin
CropRectActual := Crop;
ShowActualSize := Actual_Size;
ShowCropped := Show_Cropped;
valid_crop := validcrop(CropRectActual,Origpict);
HideNow;
picture.assign(Origpict);
SizeAndShow;
end;
screen.cursor := SaveCursor;
end;
{------------------------------------------------------------------------}
function TSimage.get_filename : string;
begin
result := curfilename;
end;
{------------------------------------------------------------------------}
function TSimage.get_rect : Trect;
begin
result := CropRectActual;
end;
{------------------------------------------------------------------------}
procedure TSimage.SetDesignedSize(
t : integer;
l : integer;
w : integer;
h : integer);
begin
DesignedTop := t;
DesignedLeft := l;
DesignedWidth := w;
DesignedHeight := h;
end;
{------------------------------------------------------------------------}
procedure TSimage.GetDesignedSize(
Var t : integer;
Var l : integer;
Var w : integer;
Var h : integer);
begin
t := DesignedTop;
l := DesignedLeft;
w := DesignedWidth;
h := DesignedHeight;
end;
{------------------------------------------------------------------------}
procedure TSimage.HideNow;
begin
hide;
update; {causes hide to actually happen}
end;
{------------------------------------------------------------------------}
procedure TSimage.SizeAndShow;
var
wratio,
hratio : real;
recttop,
rectleft,
rectwidth,
rectheight,
wOffset,
hOffset : integer;
new_width,
new_height : word;
rect : Trect;
begin
if valid_crop and ShowCropped then
begin
with CropRectActual do
begin
recttop := top;
rectleft := left;
rectwidth := right - left + 1;
rectheight := bottom - top + 1;
end
end
else
begin
with Picture do
begin
recttop := 0;
rectleft := 0;
rectwidth := width;
rectheight := height;
end;
end;
if (rectwidth <> 0) and (rectheight <> 0) then
begin
if ShowActualSize then
begin
sratio := 1.0;
new_width := rectwidth;
new_height := rectheight;
end
else
begin
{scale picture proportionary to fit into full designed size best}
wratio := DesignedWidth / rectwidth;
hratio := DesignedHeight / rectheight;
if wratio > hratio then
sratio := hratio
else
sratio := wratio;
new_width := trunc(rectwidth * sratio);
new_height := trunc(rectheight * sratio);
if new_width > DesignedWidth then new_width := DesignedWidth;
if new_height > DesignedHeight then new_Height := DesignedHeight;
end;
wOffset := (DesignedWidth - new_width) div 2;
if wOffset < 0 then wOffset := 0;
hOffset := (DesignedHeight - new_height) div 2;
if hOffset < 0 then hOffset := 0;
SetStretchBltMode(picture.bitmap.canvas.handle,STRETCH_DELETESCANS);
if sratio < 1 then
begin
With picture.bitmap.canvas do
StretchBlt(handle,0,0,new_width,new_height
,handle,rectleft,recttop,rectwidth,rectheight,srccopy);
end
else
if sratio > 1 then
begin
picture.bitmap.height := new_height;
picture.bitmap.width := new_width;
With picture.bitmap.canvas do
StretchBlt(handle,0,0,new_width,new_height
,OrigPict.Bitmap.canvas.handle
,rectleft,recttop,rectwidth,rectheight,srccopy);
end
else {sratio = 1}
begin
if valid_crop and ShowCropped and ShowActualSize then
With picture.bitmap.canvas do
StretchBlt(handle,0,0,new_width,new_height
,handle,rectleft,recttop,rectwidth,rectheight,srccopy);
end;
SetBounds(DesignedLeft + wOffset,DesignedTop + hOffset
,new_width,new_height);
end;
show;
end;
{------------------------------------------------------------------------}
procedure TSimage.erasecrop;
begin
picture.bitmap.canvas.CopyRect(CropOutside,CropCopy.canvas,CropOutside);
end;
{------------------------------------------------------------------------}
procedure TSimage.croptool_off(
var changed : boolean;
var Crop : Trect);
begin
if CropToolOn then
begin
erasecrop;
CropCopy.free;
CropToolOn := no;
{scale crop back to original picture units}
CropRectActual := CropRectScaled;
with CropRectActual do
begin
left := trunc(left / sratio);
right := trunc(right / sratio);
top := trunc(top / sratio);
bottom := trunc(bottom / sratio);
end;
changed := CropChanged;
Crop := CropRectActual;
valid_crop := validcrop(CropRectActual,Origpict);
end;
end;
{------------------------------------------------------------------------}
procedure TSimage.draw_croptool(
Crop : Trect);
{------------------------------------------------------------------------}
procedure corner( which : TCropHandle;
x,y : integer);
begin
with canvas do
begin
brush.color := clwhite;
case which of
UR :
begin
fillrect(rect(x+1,y-5,x+6,y));
cropHands[which] := rect(x,y-6,x+7,y+1);
end;
UL :
begin
fillrect(rect(x-5,y-5,x,y));
cropHands[which] := rect(x-6,y-6,x+1,y+1);
end;
BR :
begin
fillrect(rect(x+1,y+1,x+6,y+6));
cropHands[which] := rect(x,y,x+7,y+7);
end;
BL :
begin
fillrect(rect(x-5,y+1,x,y+6));
cropHands[which] := rect(x-6,y,x+1,y+7);
end;
RS :
begin
fillrect(rect(x+2,y-2,x+6,y+3));
cropHands[which] := rect(x+1,y-3,x+7,y+4);
end;
LS :
begin
fillrect(rect(x-5,y-2,x-1,y+3));
cropHands[which] := rect(x-6,y-3,x,y+4);
end;
TS :
begin
fillrect(rect(x-2,y-5,x+3,y-1));
cropHands[which] := rect(x-3,y-6,x+4,y);
end;
BS :
begin
fillrect(rect(x-2,y+2,x+3,y+6));
cropHands[which] := rect(x-3,y+1,x+4,y+7);
end;
end;
brush.color := clblack;
framerect(cropHands[which]);
end;
end;
{------------------------------------------------------------------------}
{------------------------------------------------------------------------}
begin
with CropRectScaled do {rect is actual pixels desired}
begin
{save the hot area coors}
cropOutside := rect(left-6,top-6,right+7,bottom+7);
CropHands[INNER] := rect(left-2,top-2,right+3,bottom+3);
canvas.brush.color := clwhite; {white boarder around pixels}
canvas.framerect(rect(left-1,top-1,right+2,bottom+2));
canvas.brush.color := clblack; {black frame around white}
canvas.framerect(CropHands[INNER]);
corner(UR,right,top);
corner(UL,left,top);
corner(BR,right,bottom);
corner(BL,left,bottom);
corner(RS,right,(bottom + top) div 2);
corner(LS,left,(bottom + top) div 2);
corner(TS,(right + left) div 2,top);
corner(BS,(right + left) div 2,bottom);
end;
end;
{------------------------------------------------------------------------}
procedure TSimage.croptool_on;
begin;
if CropToolOn then exit;
CropToolOn := yes;
CropChanged := no;
CropCopy := TBitmap.create;
CropCopy.assign(picture.bitmap);
if not valid_crop then
with CropRectActual, origpict do
begin
left := width div 4;
right := 3 * left;
top := height div 4;
bottom := 3 * top;
end;
with CropRectActual do
begin
CropRectScaled.left := trunc(left * sratio);
CropRectScaled.right := trunc(right * sratio);
CropRectScaled.top := trunc(top * sratio);
CropRectScaled.bottom := trunc(bottom * sratio);
end;
draw_croptool(CropRectScaled);
end;
{no Initialization Block}
{------------------------------------------------------------------------}
end.